
	/************************************************************************************************

		@API
		Class: jsl.Dir

		Constructor:
			dir		Dir						(path*)

		Base:
			dir		create				(overwrite*)
			dir		remove				(force*)
			dir		clear					()
			list	read					(filter*)
			b			walk					(action, includeSelf*)
			dir		rename				(name, overwrite*)
			dir		move					(path, overwrite*)
			dir		copy					(path, overwrite*)
			dir		merge					(path)
			obj		search				(name, global*)

		Info:
			b			contains			(name)
			b			exists				()
			b			empty					()

			b			isFile				()
			b			isDir					()

			name	name					()
			path	path					()
			path	nativePath		()
			path	parent				()

			s			toString			()

		Only Static:
			dir		root					(name, path*)
			dir		tmpDir				(path*)
			dir		workingDir		(path*)

		Legend:
			name									string | regexp
			path									relative/absolute path | Dir instance | File instance
			dir					 					Dir instance
			obj										Dir/File instance
			list									Dir/File instance[]
			filter								f(obj) > b | "file" | "dir" | regexp
			action								f(obj) > b

		Abstract Path:
			separator:									/
			forbidden name characters: 	\/:*?"<>|%
			root:												[^:]+:

	************************************************************************************************/

	jsl.Class("jsl.Dir", {

		//Constructor
		//---------------------------------------------------------------------------
		Dir: function(path) {
			var tmp//!
			if(arguments.length > 1)	throw jsl.ParamError()//!

			if(arguments.length)
				this.__d = jsl.Dir.__path(path)
			else {

				tmp = jsl.Dir.tmpDir()//!
				if(!tmp.exists())	throw jsl.ParamError("dir.TmpNotFound", [ tmp ])//!

				this.__d = tmp + "/d" + jsl.Dir.__tid++
			}
		},

		//Static
		//---------------------------------------------------------------------------
		$__re1: 	"sr/^[^\\\\\\/:*?\"<>|%]+$",
		$__cwd: 	null,
		$__tmp: 	null,
		$__init: 	false,
		$__rs:		{},
		$__tid:		0,

		initializer: function() {

			var c
			var f	= String.fromCharCode
			for(var a = 97, n = 123; a < n; a++) {
				c = f(a)
				this.__rs[c] = c + ":"
			}

			//---------------------------------------------------------------------------
			__ni_fle_init && __ni_fle_init(this)
			this.name = function(path) {//!
				if(arguments.length !== 1)	throw jsl.ParamError()//!
				return this.__nme(path)
			}
		},

		//---------------------------------------------------------------------------
		$create: function(path, overwrite) {
			var dir//!
			if(arguments.length > 2)	throw jsl.ParamError()//!

			if(arguments.length) 	dir = new this(this.__path(path)) //<-stacktrace clean
			else 									dir = new this

			this.__create(dir + "", arguments.length === 2 ? overwrite : false)
			return dir
		},
		//---------------------------------------------------------------------------
		$remove: function(path, force) {//!
			if(!arguments.length || arguments.length > 2)					throw jsl.ParamError()
			if(arguments.length === 2)														jsl.validate(force, "b", "force")
			if(!force && this.exists(path) && !this.empty(path))	throw jsl.ParamError("dir.NotEmpty", [ path ])//!

			this.__remove.apply(this, arguments)
			return new this(path)
		},
		//---------------------------------------------------------------------------
		$clear: function(path) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			this.__clear(path)
			return new this(path)
		},
		//---------------------------------------------------------------------------
		$read: function(path, filter) {//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()//!
			return this.__read.apply(this, arguments)
		},
		//---------------------------------------------------------------------------
		$walk: function(path, action, includeSelf) {//!
			if(arguments.length < 2 || arguments.length > 3)	throw jsl.ParamError()//!
			return this.__walk.apply(this, arguments)
		},
		//---------------------------------------------------------------------------
		$rename: function(path, name, overwrite) {//!
			if(arguments.length < 2 || arguments.length > 3)	throw jsl.ParamError()//!
			return new this(this.__rename.apply(this, arguments))
		},
		//---------------------------------------------------------------------------
		$move: function(path, path2, overwrite) {//!
			if(arguments.length < 2 || arguments.length > 3)	throw jsl.ParamError()//!

			if(arguments.length === 2)	this.__move(path, this.__path(path2, "path2"))
			else												this.__move(path, this.__path(path2, "path2"), overwrite)
			return new this(path2)
		},
		//---------------------------------------------------------------------------
		$copy: function(path, path2, overwrite) {//!
			if(arguments.length < 2 || arguments.length > 3)	throw jsl.ParamError()//!

			if(arguments.length === 2)	this.__copy(path, this.__path(path2, "path2"))
			else												this.__copy(path, this.__path(path2, "path2"), overwrite)
			return new this(path2)
		},
		//---------------------------------------------------------------------------
		$merge: function(path, path2) {//!
			if(arguments.length !== 2)	throw jsl.ParamError()//!
			this.__merge(path, this.__path(path2, "path2"))
			return new this(path2)
		},
		//---------------------------------------------------------------------------
		$search: function(path, name, global) {//!
			if(arguments.length < 2 || arguments.length > 3)	throw jsl.ParamError()//!
			return this.__search.apply(this, arguments)
		},
		//---------------------------------------------------------------------------
		$contains: function(path, name) {//!
			if(arguments.length !== 2)	throw jsl.ParamError()//!
			return this.__contains(path, name)
		},
		//---------------------------------------------------------------------------
		$exists: function(path) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			return !!this.__exists(path)
		},
		//---------------------------------------------------------------------------
		$isFile: function(path) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			return this.__exists(path) === 1
		},
		//---------------------------------------------------------------------------
		$isDir: function(path) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			return this.__exists(path) === 2
		},
		//---------------------------------------------------------------------------
		$empty: function(path) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			return this.__empty(path)
		},
		//---------------------------------------------------------------------------
		$name: function(path) {//!
			if(arguments.length > 1)	throw jsl.ParamError()//!
			return this.__nme(path)
		},
		//---------------------------------------------------------------------------
		$path: function(path) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			return this.__path(path)
		},
		//---------------------------------------------------------------------------
		$nativePath: function(path) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			return this.__nativePath(path)
		},
		//---------------------------------------------------------------------------
		$parent: function(path) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			return this.__parent(path)
		},
		//---------------------------------------------------------------------------
		$tmpDir: function(path) {
			var tmp, v, d, i, p//!
			if(arguments.length > 1)	throw jsl.ParamError()//!

			if(arguments.length) {
				d = this.__path(path)//!
				i = this.__exists(d)
				if(i === 1)	throw jsl.ParamError("dir.OpError", [ d ])
				p = this.__parent(d)
				if(p && !this.__exists(p))	throw jsl.ParamError("dir.NotFound", [ p ])//!

				this.__tmp = d
				v = new this(d)
			}
			else {
				if(!this.__tmp)	{
					tmp 				= this.workingDir() + "/tmp"
					this.__tmp	= tmp//!
					if(this.__ni_exists(tmp) === 1)	throw jsl.ConfigError("dir.TmpCreateError", [ tmp ])//!
				}

				//the tmp dir can be manually set before requested. The init
				//must be always executed the fist time
				if(!this.__init) {
					this.remove(this.__tmp, true)
					this.create(this.__tmp)
					this.__init = true
				}

				v = new this(this.__tmp)
			}

			return v
		},
		//---------------------------------------------------------------------------
		$workingDir: function(path) {
			var v, d, i//!
			if(arguments.length > 1)	throw jsl.ParamError()//!

			if(arguments.length) {
				d = this.__path(path)//!
				i = this.__exists(d)
				if(!i)			throw jsl.ParamError("dir.NotFound"	, [ d ])
				if(i === 1)	throw jsl.ParamError("dir.OpError"	, [ d ])//!

				this.__ni_cwd(path)
				this.__cwd = d
				v = new this(d)
			}
			else {
				if(!this.__cwd)	this.__cwd = this.__ni_cwd().replace(/\\/g, "/")
				v = new this(this.__cwd)
			}

			return v
		},
		//---------------------------------------------------------------------------
		$root: function(name, path) {
			var p, np, v, nm//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()
			jsl.validate(name, this.__re1, "name")//!

			if(arguments.length === 1) {
				nm 	= name.toLowerCase()
				v		= this.__rs[nm] ? new this(this.__rs[nm]) : null
			}
			else if(path == null)
				if(name.match(/[a-zA-Z]/)) this.__rs[name.toLowerCase()] = name.toLowerCase() + ":"
				else delete this.__rs[name.toLowerCase()]

			else {
				p		= this.__path(path)
				np 	= this.__nativePath(path)
				this.__rs[name.toLowerCase()] = np
				v = new this(p)
			}

			return v
		},

		//Regular
		//---------------------------------------------------------------------------
		create: function(overwrite) {//!
			if(arguments.length > 1)	throw jsl.ParamError()//!

			if(arguments.length)	jsl.Dir.__create(this.__d, overwrite)
			else									jsl.Dir.__create(this.__d)
			return this
		},
		//---------------------------------------------------------------------------
		remove: function(force) {//!
			if(arguments.length > 1)											throw jsl.ParamError()
			if(arguments.length)													jsl.validate(force, "b", "force")
			if(!force && this.exists() && !this.empty())	throw jsl.ParamError("dir.NotEmpty", [ this.__d ])//!
			jsl.Dir.__remove(this.__d)
			return this
		},
		//---------------------------------------------------------------------------
		clear: function() {//!
			if(arguments.length)	throw jsl.ParamError()//!
			jsl.Dir.__clear(this.__d)
			return this
		},
		//---------------------------------------------------------------------------
		read: function(filter) {//!
			if(arguments.length > 1)	throw jsl.ParamError()//!

			if(arguments.length)	return jsl.Dir.__read(this.__d, filter)
			else									return jsl.Dir.__read(this.__d)
		},
		//---------------------------------------------------------------------------
		walk: function(action, includeSelf) {//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()//!

			if(arguments.length === 1)	return jsl.Dir.__walk(this.__d, action)
			else												return jsl.Dir.__walk(this.__d, action, includeSelf)
		},
		//---------------------------------------------------------------------------
		rename: function(name, overwrite) {
			var path//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()//!

			if(arguments.length === 1)	path = jsl.Dir.__rename(this.__d, name)
			else												path = jsl.Dir.__rename(this.__d, name, overwrite)

			return new jsl.Dir(path)
		},
		//---------------------------------------------------------------------------
		move: function(path, overwrite) {//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()//!

			if(arguments.length === 1)	jsl.Dir.__move(this.__d, path)
			else												jsl.Dir.__move(this.__d, path, overwrite)

			return new jsl.Dir(path)
		},
		//---------------------------------------------------------------------------
		copy: function(path, overwrite) {//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()//!

			if(arguments.length === 1)	jsl.Dir.__copy(this.__d, path)
			else												jsl.Dir.__copy(this.__d, path, overwrite)

			return new jsl.Dir(path)
		},
		//---------------------------------------------------------------------------
		merge: function(path) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			jsl.Dir.__merge(this.__d, path)
			return new jsl.Dir(path)
		},
		//---------------------------------------------------------------------------
		search: function(name, global) {//!
			if(!arguments.length || arguments.length > 2)	throw jsl.ParamError()//!

			if(arguments.length === 1)	return jsl.Dir.__search(this.__d, name)
			else												return jsl.Dir.__search(this.__d, name, global)
		},
		//---------------------------------------------------------------------------
		contains: function(name) {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			return jsl.Dir.__contains(this.__d, name)
		},
		//---------------------------------------------------------------------------
		exists: function() {//!
			if(arguments.length) throw jsl.ParamError()//!
			return !!jsl.Dir.__exists(this.__d)
		},
		//---------------------------------------------------------------------------
		isFile: function() {//!
			if(arguments.length)	throw jsl.ParamError()//!
			return jsl.Dir.__exists(this.__d) === 1
		},
		//---------------------------------------------------------------------------
		isDir: function() {//!
			if(arguments.length)	throw jsl.ParamError()//!
			return jsl.Dir.__exists(this.__d) === 2
		},
		//---------------------------------------------------------------------------
		empty: function() {//!
			if(arguments.length) throw jsl.ParamError()//!
			return jsl.Dir.__empty(this.__d)
		},
		//---------------------------------------------------------------------------
		name: function() {//!
			if(arguments.length) throw jsl.ParamError()//!
			return jsl.Dir.__nme(this.__d)
		},
		//---------------------------------------------------------------------------
		path: function() {//!
			if(arguments.length) throw jsl.ParamError()//!
			return jsl.Dir.__path(this.__d)
		},
		//---------------------------------------------------------------------------
		nativePath: function() {//!
			if(arguments.length) throw jsl.ParamError()//!
			return jsl.Dir.__nativePath(this.__d)
		},
		//---------------------------------------------------------------------------
		parent: function() {//!
			if(arguments.length) throw jsl.ParamError()//!
			return jsl.Dir.__parent(this.__d)
		},
		//---------------------------------------------------------------------------
		toString: function() {
			//no arguments.length check
			return this.__d
		}
	})

	//hidden: no stacktrace
	//---------------------------------------------------------------------------
	jsl.Dir.__create = function(path, overwrite) {
		var d, i, p

		d	= this.__path(path)
		i	= this.__exists(d)

		//!
		if(i === 1)									throw jsl.ParamError("dir.OpError"			, [ d ])
		if(arguments.length === 2)	jsl.validate(overwrite, "b", "overwrite")
		if(i === 2 && !+overwrite)	throw jsl.ParamError("dir.CreationError", [ d ])

		p = this.__parent(d)
		if(p && !this.__exists(p))	throw jsl.ParamError("dir.PathNotFound"	, [ p ])//!

		if(i)	this.__remove(d)
		this.__ni_create(this.__nativePath(d))
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__remove = function(path) {
		var d, i

		d = this.__path(path)
		i	= this.__exists(d)

		//!
		if(i === 1)						throw jsl.ParamError("dir.OpError"		, [ d ])
		if(!this.__parent(d))	throw jsl.ParamError("OperationDenied", [ d ])//!
		if(i) this.__ni_remove(this.__nativePath(d))
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__clear = function(path) {
		var d, i, ls

		d	= this.__path(path)
		i	= this.__exists(d)//!
		if(!i) 			throw jsl.ParamError("dir.NotFound"	, [ d ])
		if(i === 1)	throw jsl.ParamError("dir.OpError"	, [ d ])//!

		ls = this.__read(d)

		for(var a = 0, l = ls.length; a < l; a++)
			ls[a].isDir() ? ls[a].remove(true) : ls[a].remove()
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__read = function(path, filter) {
		var d, i, Dir, File, ft, ls, ls2, b, id, f, obj

		d = this.__path(path)
		i	= this.__exists(d)//!
		if(!i) 														throw jsl.ParamError("dir.NotFound"	, [ d ])
		if(i === 1)												throw jsl.ParamError("dir.OpError"	, [ d ])
		if(arguments.length === 2)
			if(jsl.isString(filter))				jsl.validate(filter, "s(dir,file)", "filter")
			else if(!jsl.isRegExp(filter))	jsl.validate(filter, "f"					, "filter")//!

		Dir		= jsl.Dir
		File	= jsl.File

		if(filter == "file")							ft = 1
		else if(filter == "dir")					ft = 2
		else if(filter instanceof RegExp)	ft = 3
		else if(filter)										ft = 4

		ls 	= this.__ni_read(this.__nativePath(d))
		ls2	= []
		b		= 0
		d	 += "/"

		for(var a = 0, l = ls.length; a < l; a++) {

			id 	= d + ls[a]
			f		=	this.isDir(id) ? Dir : File

			//1 - all
			if(!ft)
				ls2[a] = new f(id)

			//2 - file filter
			else if(ft === 1) {
				if(f === File) ls2[b++] = new f(id)
			}

			//3 - dir filter
			else if(ft === 2) {
				if(f === Dir) ls2[b++] = new f(id)
			}

			//4 - regexp filter
			else if(ft === 3) {
				if(ls[a].search(filter) !== -1) ls2[b++] = new f(id)
			}

			//5 - function filter
			else {
				obj = new f(id)

				try 			{ if(filter(obj)) ls2[b++] = obj 								}
				catch(e) 	{ throw jsl.ParamError("BadScript:filter", e) 	}
			}
		}

		return ls2
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__walk = function(path, action, includeSelf) {
		var d, i, ls, b, id

		try {
			d	= this.__path(path)//!
			i	= this.__exists(d)
			if(!i) 			throw jsl.ParamError("dir.NotFound"	, [ d ])
			if(i === 1)	throw jsl.ParamError("dir.OpError"	, [ d ])
			jsl.validate(action, "f", "action")
			if(arguments.length === 3)	jsl.validate(includeSelf, "b", "includeSelf")//!

			if(+includeSelf && !arguments.callee.__i) {
				b	= action(new jsl.Dir(d))
				i	= this.__ni_exists(d)
			}

			arguments.callee.__i++

			if(!b && (!+includeSelf || i === 2)) {
				ls = this.__read(d)
				for(var a = 0, l = ls.length; a < l && !b; a++) {

					id 	= ls[a].nativePath()

					try 			{ b = action(ls[a]) 														}
					catch(e) 	{ throw jsl.ScriptError("BadScript:action", e) 	}

					if(!b && this.__ni_exists(id) === 2)
						b = this.__walk(id, action)
				}
			}

			arguments.callee.__i--
			return !!b
		}
		catch(e) {
			arguments.callee.__i = 0
			throw e
		}
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__rename = function(path, name, overwrite) {
		var d, i, nm, d2, nd

		d 	= this.__path(path)
		nd	= this.__nativePath(d)
		i		= this.__exists(d)

		//!
		if(!i)										throw jsl.ParamError("dir.NotFound"		, [ d ])
		if(i === 1)								throw jsl.ParamError("dir.OpError"		, [ d ])
		if(!this.__parent(nd))		throw jsl.ParamError("OperationDenied", [ d ])
		jsl.validate(name, this.__re1, "name")
		if(arguments.length === 3)	jsl.validate(overwrite, "b", "overwrite")//!

		nm = name.replace(/^\s+|\s+$/g, "")
		d2 = this.__parent(d) + "/" + nm

		if(this.__nme(nd) !== nm) {

			i	= this.__exists(d2)

			//!
			if(i === 1)									throw jsl.ParamError("dir.OpError"			, [ d ])
			if(i === 2 && !+overwrite)	throw jsl.ParamError("dir.RenameError"	, [ d ])//!

			if(i) this.__remove(d2)
			this.__ni_rename(nd, this.__nativePath(d2))
		}

		return d2
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__move = function(path, path2, overwrite) {
		var d, d2, i, p, nd, nd2

		d 	= this.__path(path)
		d2 	= this.__path(path2)
		nd	= this.__nativePath(d)
		nd2	= this.__nativePath(d2)

		if(nd !== nd2) {
			i	= this.__exists(d)//!
			if(!i)											throw jsl.ParamError("dir.NotFound"	, [ d ])
			if(i === 1)									throw jsl.ParamError("dir.OpError"	, [ d ])

			i	= this.__exists(d2)
			if(i === 1)									throw jsl.ParamError("dir.MoveError"	, [ d ])
			if(i === 2 && !+overwrite)	throw jsl.ParamError("dir.MoveError2"	, [ d ])

			p = this.__parent(nd2)
			if(!this.__exists(p))				throw jsl.ParamError("dir.PathNotFound", [ d2 ])
			if(arguments.length === 3)	jsl.validate(overwrite, "b", "overwrite")

			while(p) {
				if(nd === p)	throw jsl.ParamError("OperationDenied:move")
				p = jsl.Dir.parent(p)
			}//!

			if(i) this.__remove(d2)
			this.__ni_move(nd, nd2)
		}
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__copy = function(path, path2, overwrite) {
		var d, d2, i, p, nd, nd2

		d 	= this.__path(path)
		d2 	= this.__path(path2)
		nd	= this.__nativePath(d)
		nd2	= this.__nativePath(d2)

		if(nd !== nd2) {
			i	= this.__exists(d)//!
			if(!i)											throw jsl.ParamError("dir.NotFound"	, [ d ])
			if(i === 1)									throw jsl.ParamError("dir.OpError"	, [ d ])

			i	= this.__exists(d2)
			if(i === 1)									throw jsl.ParamError("dir.CopyError"	, [ d ])
			if(i === 2 && !+overwrite)	throw jsl.ParamError("dir.CopyError2"	, [ d ])

			p = this.__parent(nd2)
			if(!this.__exists(p))				throw jsl.ParamError("dir.PathNotFound", [ d2 ])
			if(arguments.length === 3)	jsl.validate(overwrite, "b", "overwrite")

			while(p) {
				if(nd === p)	throw jsl.ParamError("OperationDenied:move")
				p = jsl.Dir.parent(p)
			}//!

			if(i) this.__remove(d2)
			this.__ni_copy(nd, nd2)
		}
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__merge = function(path, path2) {
		var d, d2, i, ls, nd, nd2, id1, id2, i1, i2, p

		d		= this.__path(path)
		d2	= this.__path(path2)
		nd	= this.nativePath(d)
		nd2 = this.nativePath(d2)

		//!
		i	= this.__exists(d)
		if(!i)			throw jsl.ParamError("dir.NotFound"	, [ d ])
		if(i === 1)	throw jsl.ParamError("dir.OpError"	, [ d ])

		i	= this.__exists(d2)
		if(!i)			throw jsl.ParamError("dir.NotFound"	, [ d2 ])
		if(i === 1)	throw jsl.ParamError("dir.OpError"	, [ d2 ])//!

		if(nd !== nd2) {//!

			p = jsl.Dir.parent(nd2)
			while(p) {
				if(nd === p)	throw jsl.ParamError("OperationDenied:move")
				p = jsl.Dir.parent(p)
			}//!

			ls	= this.__ni_read(nd)
			nd 	= nd 	+ "/"
			nd2	= nd2 + "/"

			for(var a = 0, l = ls.length; a < l; a++) {

				id1 = nd 	+ ls[a]
				id2 = nd2 + ls[a]

				i1	= this.__ni_exists(id1)
				i2 	= this.__ni_exists(id2)

				//1-dir
				if(i1 === 2)
					if(i2 === 2)
						this.__merge(id1, id2)
					else {
						if(i2 === 1) 	jsl.File.__remove(id2)
						this.__copy(id1, id2)
					}
				//2-file
				else {
					if(i2 === 2)	this.__ni_remove(id2)
					jsl.File.__copy(id1, id2, true)
				}
			}
		}
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__search = function(path, name, global) {
		var d, i, ls, nd, re, id, b, g, a, l, c, os, os2, o, rv

		d 	= this.__path(path)
		re	= name instanceof RegExp//!
		i		= this.__ni_exists(d)

		if(!i)											throw jsl.ParamError("dir.NotFound"	, [ d ])
		if(i === 1)									throw jsl.ParamError("dir.OpError"	, [ d ])
		if(!re)											jsl.validate(name		, "s+", "name")
		if(arguments.length === 3)	jsl.validate(global	, "b"	, "global")//!

		nd	= this.__nativePath(d)
		ls 	= this.__ni_read(nd)
		g		= +global
		nd	= nd + "/"

		if(g) {

			os 	= []
			c		= 0

			for(a = 0, l = ls.length; a < l; a++) {

				id 	= nd + ls[a]
				i		= this.__ni_exists(id)

				if(re)	b = name.test(id)
				else 		b = id.indexOf(name) !== -1

				if(b)
					os[c++] = i === 1 ? new jsl.File(id) : new jsl.Dir(id)

				if(i === 2)	{
					os2 = this.__search(id, name, true)
					if(os2)	os = os.concat(os2)
				}
			}

			rv = os.length ? os : null
		}
		else {
			for(a = 0, l = ls.length; a < l && !o; a++) {

				id 	= nd + ls[a]
				i		= this.__ni_exists(id)

				if(re)	b = name.test(id)
				else 		b = id.indexOf(name) !== -1

				if(b)							o = i === 1 ? new jsl.File(id) : new jsl.Dir(id)
				else if(i === 2)	o = this.__search(id, name)
			}

			rv = o || null
		}

		return rv
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__contains = function(path, name) {
		var d, i, ls, re, b

		d 	= this.__path(path)
		re	= name instanceof RegExp//!
		i 	= this.__exists(d)

		if(!i)			throw jsl.ParamError("dir.NotFound"	, [ d ])
		if(i === 1)	throw jsl.ParamError("dir.OpError"	, [ d ])
		if(!re)			jsl.validate(name, "sr/^[^\\\\\\/]+$", "name")//!

		ls = this.__read(path)
		for(var a = 0, l = ls.length; a < l && !b; a++)
			if(re) 	b = ls[a].name().search(name)		!== -1
			else		b = ls[a].name().indexOf(name)	!== -1

		return !!b
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__exists = function(path) {
		return this.__ni_exists(this.__nativePath(path))
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__empty = function(path) {
		var d, i

		d = this.__path(path)//!
		i = this.__exists(d)
		if(!i)			throw jsl.ParamError("dir.NotFound"	, [ d ])
		if(i === 1)	throw jsl.ParamError("dir.OpError"	, [ d ])//!

		return this.__ni_empty(this.__nativePath(d))
	}
	//---------------------------------------------------------------------------
	jsl.Dir.__nme = jsl.File.__nme
	//---------------------------------------------------------------------------
	jsl.Dir.__path = jsl.File.__path
	//---------------------------------------------------------------------------
	jsl.Dir.__nativePath = jsl.File.__nativePath
	//---------------------------------------------------------------------------
	jsl.Dir.__parent = jsl.File.__parent
	//---------------------------------------------------------------------------
	jsl.File.__path = jsl.Dir.__path = function(path, name) {
		var f, r, nr

		if(path instanceof jsl.File || path instanceof jsl.Dir)
			f = path + ""
		else {//!
			jsl.validate(path, "s+", name || "path")//!

			f = path.replace(/\s*(\\|\/)\s*/g, "/").replace(/^\s+|\s+$/g, "")
			r = f.match(/^([^:]+):/)

			if(r) {
				nr = jsl.Dir.__rs[r[1]] === r[1] + ":" ? r[1] + ":" : jsl.Dir.root(r[1])//!
				if(!nr) throw jsl.ParamError("dir.RootNotDefined", [ r[1] ])
				jsl.validate(f, "sr/^[^:]+:(\/[^\\\\\\/:*?\"<>|%]+)*\/?$", [ path ])//!
			}
			else {//!
				if(!jsl.File.__ni_path_valid(f)) 		throw jsl.ParamError("BadValue", [ path ])//!
				if(jsl.File.__ni_path_relative(f))	f = (jsl.Dir.__cwd || jsl.Dir.workingDir()) + "/" + f.replace(/^\//, "")
			}

			if(f.indexOf(".") !== -1) {

				f = f.split("/")

				for(var a = 0, l = f.length; a < l; a++)
					if(f[a] === ".")
						f.splice(a--, 1)
					else if(f[a] === "..")
						if(a > 1)	f.splice(--a, 2), a--
						else			f.splice(a--, 1)

				f = f.join("/")
			}

			f =	f.replace(/\/$/, "")
		}

		return f
	}
